package com.dly.blog.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dly.blog.domain.FreeFrequency;
import com.dly.blog.domain.User;
import com.dly.blog.domain.ro.GetCodeRO;
import com.dly.blog.domain.ro.ParseCodeRO;
import com.dly.blog.enums.FreeType;
import com.dly.blog.exception.ChatExceptionEnum;
import com.dly.blog.mapper.FreeFrequencyMapper;
import com.dly.blog.provider.user.UserProvider;
import com.dly.blog.queue.OverdueCodeQueue;
import com.dly.blog.service.FreeFrequencyService;
import com.dly.blog.utile.SecurityUtils;
import lombok.AllArgsConstructor;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;

@Service
@AllArgsConstructor
public class FreeFrequencyServiceImpl extends ServiceImpl<FreeFrequencyMapper, FreeFrequency> implements FreeFrequencyService {

    private final UserProvider userProvider;

    private final OverdueCodeQueue overdueCodeQueue;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String getCode(GetCodeRO getCodeRO) {
        //微信关注用户字可以享受一次
       if(FreeType.WX.equals(getCodeRO.getFreeType())){
           FreeFrequency one = this.getOne(new LambdaQueryWrapper<FreeFrequency>()
                   .eq(FreeFrequency::getCreateUser, SecurityUtils.getUserId())
                   .eq(FreeFrequency::getIsUse, 1)
                   .eq(FreeFrequency::getType, getCodeRO.getFreeType()));
           if(Objects.nonNull(one)) return "已享受";
       }
        FreeFrequency one = this.getOne(new LambdaQueryWrapper<FreeFrequency>()
                .eq(FreeFrequency::getCreateUser, SecurityUtils.getUserId())
                .eq(FreeFrequency::getIsFailure, 0)
                .eq(FreeFrequency::getIsUse, 0)
                .eq(FreeFrequency::getType, getCodeRO.getFreeType())
        );
        if(Objects.nonNull(one)) return one.getCode();
        //如果是其他类型 必须有管理员来创建
        if(FreeType.OTHER.equals(getCodeRO.getFreeType()) && Objects.requireNonNull(SecurityUtils.getLoginUser()).getPermissions().stream().map(SimpleGrantedAuthority::getAuthority).noneMatch(role-> Objects.equals("ROLE_admin", role))){
            throw ChatExceptionEnum.FREQUENCY_NO_EMPTY.getChatException();
        }
        FreeFrequency freeFrequency = new FreeFrequency();
        freeFrequency.setIsUse(0);
        //如果是WX类型默认给50次
        freeFrequency.setFrequency(FreeType.WX.equals(getCodeRO.getFreeType())?50:getCodeRO.getFrequency());
        freeFrequency.setIsFailure(0);
        freeFrequency.setType(getCodeRO.getFreeType());
        freeFrequency.setCode(RandomUtil.randomString(6));
        this.save(freeFrequency);
        overdueCodeQueue.addCode(freeFrequency.getCode(), 120);
        return freeFrequency.getCode();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void parseCode(ParseCodeRO parseCodeRO) {
        FreeFrequency one = this.getOne(new LambdaQueryWrapper<FreeFrequency>()
                .eq(FreeFrequency::getCode, parseCodeRO.getCode())
                .eq(FreeFrequency::getIsUse, 0)
                .eq(FreeFrequency::getIsFailure, 0)
                .eq(FreeFrequency::getType, parseCodeRO.getType())
        );
        if(Objects.isNull(one)){
            throw ChatExceptionEnum.FREQUENCY_CODE_NULL.getChatException();
        }
        //区分类型
        if(FreeType.OTHER.equals(parseCodeRO.getType())){
            if(StrUtil.isBlank(parseCodeRO.getUserId())){
                throw ChatExceptionEnum.FREQUENCY_USER_EMPTY.getChatException();
            }
            userProvider.addFrequency(parseCodeRO.getUserId(), one.getFrequency());
        }else{
            userProvider.addFrequency(one.getCreateUser(), one.getFrequency());
        }
        this.update(new LambdaUpdateWrapper<FreeFrequency>()
                .eq(FreeFrequency::getCode, parseCodeRO.getCode())
                .eq(FreeFrequency::getType, parseCodeRO.getType())
                .set(FreeFrequency::getIsUse, 1)
        );
        if(FreeType.WX.equals(parseCodeRO.getType()) && Objects.nonNull(parseCodeRO.getOpenId())){
            userProvider.bindWX(one.getCreateUser(), parseCodeRO.getOpenId());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void overdue(String code) {
        this.update(new LambdaUpdateWrapper<FreeFrequency>()
                .eq(FreeFrequency::getCode, code)
                .setSql("is_failure = 1")
        );
    }
}
